package com.xqh.spider;

import com.alibaba.fastjson.JSON;
import com.xqh.base.util.http.HttpClientUtils;
import com.xqh.base.util.id.IdWorker;
import com.xqh.entity.ques.Vocabulary;
import lombok.Data;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 爬 词汇 信息 音标 翻译等
 */
public class SpiderWordTools {

    private static final Logger logger = LoggerFactory.getLogger(SpiderWordTools.class);

    private static final String spider_url="http://www.youdao.com/w/";

    private static final String end_url="/#keyfrom=dict2.index";

    /**
     * 释义内容 div id
     */
    private static final String word_basic_div="phrsListTab";

    /**
     * 词汇对应信息 class name
     */
    private static final String word_info_class="wordbook-js";

    /**
     * 音标区域 class name
     */
    private static final String phonetic_class = "baav";

    /**
     * 音标区域 单个 音标 span class name
     */
    private static final String phonetic_single_class = "pronounce";

    /**
     * 音标 内容 对应 span class name
     */
    private static final String phonetic_span_class = "phonetic";

    private static final String america="美";

    private static final String england="英";

    /**
     * 翻译 dom class name
     */
    private static final String translate_class = "trans-container";

    /**
     * 双语例句ID
     */
    private static final String double_example_id = "bilingual";

    /**
     * 原声例句ID
     */
    private static final String original_example_id="originalSound";


    /**
     * 英英释义 ID
     */
    private static final String engliesh_explain_id="tEETrans";

    private static final Map<String,String> headers =getReqHeaderMap();

    public static Map<String,String> getReqHeaderMap(){
        Map<String,String> headers = new HashMap<>();
        headers.put("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        headers.put("Accept-Encoding","gzip, deflate");
        headers.put("Accept-Language","zh-CN,zh;q=0.9,en;q=0.8");
        headers.put("Connection","keep-alive");
        headers.put("Cookie","DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; OUTFOX_SEARCH_USER_ID=1010675437@27.38.248.77; OUTFOX_SEARCH_USER_ID_NCOO=1049921357.8418585; _ntes_nnid=fef7db9b765553b5af510c2aecc25aad,1523443894642; search-popup-show=-1; UM_distinctid=162b794941670-07ebf7c6943f-3a614f0b-100200-162b79494176b3; P_INFO=qhx_kael@163.com|1523849604|0|search|00&99|gud&1523502868&search#gud&440300#10#0#0|&0|search&youdaodict_client|qhx_kael@163.com; tabRecord.examples=%23bilingual; tabRecord.webTrans=%23tEETrans; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcqSWBMhKlIY53mvlrlw; webDict_HdAD=%7B%22req%22%3A%22http%3A//dict.youdao.com%22%2C%22width%22%3A960%2C%22height%22%3A240%2C%22showtime%22%3A5000%2C%22fadetime%22%3A500%2C%22notShowInterval%22%3A3%2C%22notShowInDays%22%3Afalse%2C%22lastShowDate%22%3A%22Mon%20Nov%2008%202010%22%7D; ___rl__test__cookies=1523938153130");
        headers.put("Upgrade-Insecure-Requests","1");
        headers.put("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
        return headers;
    }

    public static Vocabulary spiderWord(String word){
        Vocabulary resObj = new Vocabulary();
        VocabJson vocab = new VocabJson();
        vocab.setText(word);
        String url = spider_url+encodeWord(word)+end_url;
        String response = HttpClientUtils.get(url, headers,null);
        Document document = Jsoup.parse(response);
        /**
         * 解析 释义内容
         */
        parseExplain(document, vocab);

        /**
         * 解析例句内容
         */
        parseExampleSentence(document, vocab);

        parseEnExplain(document, vocab);
        resObj.setText(word);
        resObj.setExampleSentence(JSON.toJSONString(vocab.getSentences()));
        resObj.setTranslationJson(JSON.toJSONString(vocab.getTranslations()));
        resObj.setEnExplain(JSON.toJSONString(vocab.getEnExplain()));//英英释义
        resObj.setUkPhonetic(vocab.getUk_phonetic());
        resObj.setUsPhonetic(vocab.getUs_phonetic());
        return resObj;
    }

    public static String encodeWord(String word){
        if(word.contains(" ")){
            word = word.replaceAll(" ","%20");
        }
        return word;
    }

    /**
     * 解析 释义 部分内容
     * @param document
     * @param vocab
     */
    public static void parseExplain(Document document, VocabJson vocab){
        Element explain_div = document.getElementById(word_basic_div);
        if(null != explain_div){
            //获取音标
            Elements elements = explain_div.getElementsByClass(word_info_class);
            if(null != elements && elements.size()>0){
                Element wordEle= elements.first();
                Element baav = wordEle.getElementsByClass(phonetic_class).first();
                Elements phonetics = baav.getElementsByClass(phonetic_single_class);
                for(Element el:phonetics){
                    if(el.hasText()){
                        Elements us_phlist= el.getElementsByClass(phonetic_span_class);
                        /**
                         * 因为如果是词组 短语 没有 音标 信息
                         */
                        if(null != us_phlist && us_phlist.size()>0){
                            if(el.text().contains(america)){
                                //美音
                                vocab.setUs_phonetic(el.getElementsByClass(phonetic_span_class).first().text().trim());
                            }else if(el.text().contains(england)){
                                //英音
                                vocab.setUk_phonetic(el.getElementsByClass(phonetic_span_class).first().text().trim());
                            }else{
                                //不包含 "英, 美" 音标区分
                                vocab.setUs_phonetic(el.getElementsByClass(phonetic_span_class).first().text().trim());
                                vocab.setUk_phonetic(el.getElementsByClass(phonetic_span_class).first().text().trim());
                            }
                        }
                    }
                }
            }

            //获取 翻译信息
            Elements translates = explain_div.getElementsByClass(translate_class);
            if(null != translates && translates.size()>0){
                List<String> tlist=new ArrayList<>();
                Elements transList = translates.first().getElementsByTag("li");
                for(Element ele : transList){
                    tlist.add(ele.text().trim());
                }
                vocab.setTranslations(tlist);
            }
        }
    }

    /**
     * 解析英英释义
     * @param document
     * @param vocab
     */
    public static void parseEnExplain(Document document, VocabJson vocab){
        Element ele = document.getElementById(engliesh_explain_id);
        if(null != ele){
            Elements container = ele.getElementsByClass("trans-container");
            if(null != container && container.size()>0){
                Elements ols = container.first().getElementsByClass("ol");
                if(null != ols && ols.size()>0){
                    Elements liEles = ols.first().getElementsByTag("li");
                    List<EnglishExplain> enExplain = new ArrayList<>();
                    for(Element li:liEles){
                        EnglishExplain ee = new EnglishExplain();
                        ee.setExplain(li.getElementsByTag("span").first().text());
                        if(li.getElementsByClass("gray").size()>0){
                            //同义词
                            ee.setSynonym(li.getElementsByClass("gray").first().getElementsByClass("search-js").first().text());
                        }
                       enExplain.add(ee);
                    }
                    vocab.setEnExplain(enExplain);
                }
            }
        }
    }

    /**
     * 解析双语例句
     * @param document
     * @param vocab
     */
    public static void parseExampleSentence(Document document, VocabJson vocab){
         Element element = document.getElementById(double_example_id);
         List<ExampleSentence> elist = new ArrayList<>();
         if(null != element){

             Elements li_list = element.getElementsByClass("ol").first().getElementsByTag("li");
             for(Element li:li_list){
                 ExampleSentence sentence = new ExampleSentence();
                 Elements tagPlist = li.getElementsByTag("p");
                 String eg_sentence = tagPlist.first().text();//例句

                 String eg_translate = tagPlist.get(1).text();

                 String eg_resource = tagPlist.last().text();
                 sentence.setSentence(eg_sentence);
                 sentence.setTranslation(eg_translate);
                 sentence.setResource(eg_resource);
                 elist.add(sentence);
             }
             vocab.setSentences(elist);
        }else{
             //没有双语例句. 抓取 原声例句
             Element ele = document.getElementById(original_example_id);
             if(null != ele){
                 Elements li_list = ele.getElementsByClass("ol").first().getElementsByTag("li");
                 for(Element li:li_list){
                     Elements tagPlist = li.getElementsByTag("p");
                     if(tagPlist.size()>=3){
                         ExampleSentence sentence = new ExampleSentence();
                         String eg_sentence = tagPlist.first().text();//例句

                         String eg_translate = tagPlist.get(1).text();

                         String eg_resource = tagPlist.last().text();
                         sentence.setSentence(eg_sentence);
                         sentence.setTranslation(eg_translate);
                         sentence.setResource(eg_resource);
                         elist.add(sentence);
                     }
                 }
                 vocab.setSentences(elist);
             }
         }
    }


    /**
     * 词汇表
     */
    @Data
    public static class VocabJson {

        private String text;

        private String us_phonetic;//美音 音标

        private String uk_phonetic;//英音 音标

        private List<String> translations;//翻译

        private List<ExampleSentence> sentences;//对应例句

        private List<EnglishExplain> enExplain;//英英释义
    }

    /**
     * 例句
     */
    @Data
    public static class ExampleSentence{

        private String sentence;//例句

        private String translation;//翻译

        private String resource;//来源
    }

    @Data
    public static class EnglishExplain{

        private String explain;//英英释义

        private String synonym;//同义词
    }


    public static void main(String[] args){

        Vocabulary vocab = spiderWord("a lot of");
        System.out.println(JSON.toJSONString(vocab));
    }
}
